package evolution.operation.selection;

import evolution.individual.Individual;
import evolution.random.RandomGenerator;

public class RouletteWheelSelection implements SelectionStrategy {

	private RandomGenerator randomGenerator;

	/**
	 * {@link Individual}s must have positive fitness values.
	 */
	@Override
	public Individual[] select(Individual[] source) {
		int length = source.length;
		double fitnessSum = 0;
		double[] roulette = new double[length];

		for (int i = 0; i < length; i++) {
			Individual individual = source[i];
			fitnessSum += individual.getFitness();
			roulette[i] = fitnessSum;
		}

		Individual[] selected = new Individual[length];

		for (int i = 0; i < length; i++) {
			double random = randomGenerator.nextDouble() * fitnessSum;

			int idx = 0;
			while (random > roulette[idx]) {
				idx++;
			}
			selected[i] = source[idx];
		}

		return selected;
	}

	public RandomGenerator getRandomGenerator() {
		return randomGenerator;
	}

	public void setRandomGenerator(RandomGenerator randomGenerator) {
		this.randomGenerator = randomGenerator;
	}
}
